package com.example.aidlclientdemo;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.example.aidlservicedemo.IBinderPool;

import java.util.concurrent.CountDownLatch;

/**
 * BinderPool 是一个用于管理与 Binder 池服务连接的单例类。
 * 它负责绑定远程服务、查询指定的 Binder 对象，并提供连接管理和异常处理功能。
 *
 * @author 猿小蔡
 * @since 2025/6/28
 */
public class BinderPool {

    /**
     * 用于日志输出的 TAG 标识。
     */
    private static final String TAG = "BinderPool";

    /**
     * BinderPool 的单例实例，使用 volatile 关键字确保多线程环境下的可见性。
     */
    private static volatile BinderPool instance;

    /**
     * 应用上下文对象，用于绑定和解绑服务。
     */
    private Context context;

    /**
     * 远程 IBinderPool 接口实例，用于与 Binder 池服务进行通信。
     */
    private IBinderPool binderPool;

    /**
     * 用于等待服务连接完成的同步计数器。
     */
    private CountDownLatch connectBinderPoolCountDownLatch;

    /**
     * 私有构造函数，初始化上下文并连接 Binder 池服务。
     *
     * @param context 上下文对象
     */
    private BinderPool(Context context) {
        this.context = context.getApplicationContext();
        connectBinderPoolService();
    }

    /**
     * 获取 BinderPool 的单例实例。
     *
     * @param context 上下文对象
     * @return 返回 BinderPool 实例
     */
    public static BinderPool getInstance(Context context) {
        if (instance == null) {
            synchronized (BinderPool.class) {
                if (instance == null) {
                    instance = new BinderPool(context);
                }
            }
        }
        return instance;
    }

    /**
     * 连接 Binder 池服务，绑定远程服务并等待连接完成。
     */
    private synchronized void connectBinderPoolService() {
        // 初始化同步计数器
        connectBinderPoolCountDownLatch = new CountDownLatch(1);
        Intent service = new Intent();
        // 设置目标服务组件
        service.setComponent(new ComponentName("com.example.aidlservicedemo",
            "com.example.aidlservicedemo.BinderPoolService"));
        // 绑定远程服务
        context.bindService(service, binderPoolConnection, Context.BIND_AUTO_CREATE);
        try {
            // 等待服务连接完成
            connectBinderPoolCountDownLatch.await();
        } catch (InterruptedException e) {
            Log.e(TAG, "connectBinderPoolService interrupted", e);
        }
    }

    /**
     * 查询指定代码对应的 Binder 对象。
     *
     * @param binderCode Binder 的标识码
     * @return 返回对应的 IBinder 对象，若失败则返回 null
     */
    public IBinder queryBinder(int binderCode) {
        IBinder binder = null;
        try {
            if (binderPool != null) {
                binder = binderPool.queryBinder(binderCode);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "queryBinder failed", e);
        }
        return binder;
    }

    /**
     * 断开与 Binder 池服务的连接。
     */
    public void disconnect() {
        if (binderPool != null) {
            // 解除服务绑定
            context.unbindService(binderPoolConnection);
            binderPool = null;
        }
    }

    /**
     * ServiceConnection 实现，用于监听服务连接状态。
     */
    private ServiceConnection binderPoolConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // 获取远程 IBinderPool 接口实例
            binderPool = IBinderPool.Stub.asInterface(service);
            // 通知连接完成
            connectBinderPoolCountDownLatch.countDown();
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.w(TAG, "Service disconnected");
            // 清除 Binder 引用
            binderPool = null;
            // 尝试重新连接
            connectBinderPoolService();
        }
    };

    /**
     * 死亡代理接收器，用于监听 Binder 死亡事件。
     */
    private IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
        @Override
        public void binderDied() {
            Log.w(TAG, "binder died");
            // 解除死亡代理监听
            binderPool.asBinder().unlinkToDeath(this, 0);
            // 清除 Binder 引用
            binderPool = null;
            // 尝试重新连接
            connectBinderPoolService();
        }
    };

}
